// TLSContext.cc
#include "TLSContext.hpp"
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <iostream>

#include <openssl/engine.h>

TLSContext::TLSContext(Role role, const std::string& certFile, const std::string& keyFile)
    : ctx_(nullptr)
{
    //1.初始化 OpenSSL 库（线程安全外部保证）
    SSL_library_init();
    OpenSSL_add_all_algorithms();
    SSL_load_error_strings();

    const SSL_METHOD* method = (role == Role::Server) ? TLS_server_method() : TLS_client_method();
    ctx_ = SSL_CTX_new(method);
    if (!ctx_) {
        std::cerr << "创建SSL上下文失败 \n";
        ERR_print_errors_fp(stderr);
        throw std::runtime_error("创建SSL上下文失败");
    }

    //2.加载引擎
    // loadEngine("rdrand"); //测试
    loadDynamicEngine("./fake_engine.so", "fake");


    //3.加载证书和密钥
    if (SSL_CTX_use_certificate_file(ctx_, certFile.c_str(), SSL_FILETYPE_PEM) <= 0) {
        std::cerr << "加载证书失败 " << certFile << "\n";
        ERR_print_errors_fp(stderr);
        throw std::runtime_error("加载证书失败");
    }

    if (SSL_CTX_use_PrivateKey_file(ctx_, keyFile.c_str(), SSL_FILETYPE_PEM) <= 0) {
        std::cerr << "加载私钥失败 " << keyFile << "\n";
        ERR_print_errors_fp(stderr);
        throw std::runtime_error("加载私钥失败");
    }

    if (!SSL_CTX_check_private_key(ctx_)) {
        std::cerr << "私钥不匹配证书\n";
        throw std::runtime_error("私钥不匹配证书");
    }

    // 强制 SM  国密：ECC-SM2-WITH-SM4-SM3   套件  
    SSL_CTX_set_cipher_list(ctx_, "ECC-SM2-WITH-SM4-SM3");
}

TLSContext::~TLSContext() {
    if (ctx_) {
        SSL_CTX_free(ctx_);
    }
    if(engine_){
        // TODO 可能有问题
        // ENGINE_finish(engine_);
        // ENGINE_free(engine_);
    }
}

SSL_CTX* TLSContext::get() const {
    return ctx_;
}


void TLSContext::loadEngine(const std::string& engine_id) {
    // 初始化引擎子系统
    ENGINE_load_builtin_engines();

    ENGINE* engine = ENGINE_by_id(engine_id.c_str());
    if (!engine) {
        std::cerr << "引擎未找到 id-" << engine_id << "\n";
        return;  // 不中断，仍可使用软件方式 也可以考虑直接中断 exit
    }

    if (!ENGINE_init(engine)) {
        std::cerr << "引擎初始化失败 id-" << engine_id << "\n";
        ENGINE_free(engine);
        return;
    }

    ENGINE_set_default(engine, ENGINE_METHOD_ALL);

    std::cout << "引擎已加载: " << ENGINE_get_id(engine) << "\n";
}


bool TLSContext::loadDynamicEngine(const std::string& so_path, const std::string& engine_id) {
    // 加载内置引擎和 dynamic 引擎模块
    ENGINE_load_builtin_engines();
    ENGINE_load_dynamic(); //确保能动态加载引擎

    // 获取 dynamic 引擎（动态加载器）
    ENGINE* engine = ENGINE_by_id("dynamic");
    if (!engine) {
        std::cerr << "前置：动态引擎缺失\n";
        return false;
    }

    // 设置动态库路径
    if (!ENGINE_ctrl_cmd_string(engine, "SO_PATH", so_path.c_str(), 0)) {
        std::cerr << "设置动态库路径失败\n";
        ENGINE_free(engine);
        return false;
    }

    // 设置动态引擎ID ps必须和.so里实现的ID一致
    if (!ENGINE_ctrl_cmd_string(engine, "ID", engine_id.c_str(), 0)) {
        std::cerr << "设置动态引擎ID失败\n";
        ENGINE_free(engine);
        return false;
    }

    // 加载动态库
    if (!ENGINE_ctrl_cmd_string(engine, "LOAD", NULL, 0)) {
        std::cerr << "加载动态库失败\n";
                unsigned long err;
    while ((err = ERR_get_error()) != 0) {
    std::cerr << "[OpenSSL ERR] " << ERR_error_string(err, NULL) << "\n";
}
        ENGINE_free(engine);
        return false;
    }

    //初始化引擎
    if (!ENGINE_init(engine)) {
        std::cerr << "引擎初始化失败\n";

        ENGINE_free(engine);
        return false;
    }

    //引擎覆盖所有算法
    ENGINE_set_default(engine, ENGINE_METHOD_ALL);   

    std::cout << "引擎已成功加载 id-" << ENGINE_get_id(engine) << "\n";

    return true;
}